home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / UNIX / C / INDENT / PARSE.C < prev    next >
C/C++ Source or Header  |  1989-09-02  |  12KB  |  363 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc.
  3.  * Copyright (c) 1980 The Regents of the University of California.
  4.  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by the University of California, Berkeley, the University of Illinois,
  13.  * Urbana, and Sun Microsystems, Inc.  The name of either University
  14.  * or Sun Microsystems may not be used to endorse or promote products
  15.  * derived from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)parse.c    5.8 (Berkeley) 9/15/88";
  23. #endif /* not lint */
  24.  
  25. #include "indent_globs.h"
  26.  
  27. struct parser_state *parser_state_tos;
  28.  
  29. /* like ++parser_state_tos->tos but checks for stack overflow and extends
  30.    stack if necessary.  */
  31. static int
  32. inc_pstack ()
  33. {
  34.   if (++parser_state_tos->tos >= parser_state_tos->p_stack_size)
  35.     {
  36.       parser_state_tos->p_stack_size *= 2;
  37.       parser_state_tos->p_stack = (enum codes *)
  38.     xrealloc (parser_state_tos->p_stack,
  39.          parser_state_tos->p_stack_size * sizeof (enum codes));
  40.       parser_state_tos->il = (int *)
  41.     xrealloc (parser_state_tos->il, 
  42.           parser_state_tos->p_stack_size * sizeof (int));
  43.       parser_state_tos->cstk = (int *)
  44.     xrealloc (parser_state_tos->cstk, 
  45.           parser_state_tos->p_stack_size * sizeof (int));
  46.     }
  47.   return parser_state_tos->tos;
  48. }
  49.  
  50. void
  51. parse(tk)
  52.     enum codes tk;        /* the code for the construct scanned */
  53. {
  54.     int         i;
  55.  
  56. #ifdef debug
  57.     printf("%2d - %s\n", tk, token);
  58. #endif
  59.  
  60.     while (parser_state_tos->p_stack[parser_state_tos->tos] == ifhead && tk != elselit) {
  61.     /* true if we have an if without an else */
  62.     parser_state_tos->p_stack[parser_state_tos->tos] = stmt;    /* apply the if(..) stmt ::= stmt
  63.                      * reduction */
  64.     reduce();        /* see if this allows any reduction */
  65.     }
  66.  
  67.  
  68.     switch (tk) {        /* go on and figure out what to do with the
  69.                  * input */
  70.  
  71.     case decl:            /* scanned a declaration word */
  72.     parser_state_tos->search_brace = btype_2;
  73.     /* indicate that following brace should be on same line */
  74.     if (parser_state_tos->p_stack[parser_state_tos->tos] != decl) {    /* only put one declaration
  75.                          * onto stack */
  76.         break_comma = true;    /* while in declaration, newline should be
  77.                  * forced after comma */
  78.         parser_state_tos->p_stack[inc_pstack()] = decl;
  79.         parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
  80.  
  81.         if (ljust_decl) {/* only do if we want left justified
  82.                  * declarations */
  83.         parser_state_tos->ind_level = 0;
  84.         for (i = parser_state_tos->tos - 1; i > 0; --i)
  85.             if (parser_state_tos->p_stack[i] == decl)
  86.               /* indentation is number of declaration levels deep
  87.              we are times spaces per level */
  88.               parser_state_tos->ind_level += ind_size;
  89.         parser_state_tos->i_l_follow = parser_state_tos->ind_level;
  90.         }
  91.     }
  92.     break;
  93.  
  94.     case ifstmt:        /* scanned if (...) */
  95.     if (parser_state_tos->p_stack[parser_state_tos->tos] == elsehead
  96.         && else_if)    /* "else if ..." */
  97.         parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
  98.     case dolit:        /* 'do' */
  99.     case forstmt:        /* for (...) */
  100.     inc_pstack();
  101.     parser_state_tos->p_stack[parser_state_tos->tos] = tk;
  102.     parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  103.     parser_state_tos->i_l_follow += ind_size;    /* subsequent statements should be indented 1 */
  104.     parser_state_tos->search_brace = btype_2;
  105.     break;
  106.  
  107.     case lbrace:        /* scanned { */
  108.     break_comma = false;    /* don't break comma in an initial list */
  109.     if (parser_state_tos->p_stack[parser_state_tos->tos] == stmt || parser_state_tos->p_stack[parser_state_tos->tos] == decl
  110.         || parser_state_tos->p_stack[parser_state_tos->tos] == stmtl)
  111.       /* it is a random, isolated stmt group or a declaration */
  112.       parser_state_tos->i_l_follow += ind_size;    
  113.     else {
  114.         if (s_code == e_code) {
  115.         /*
  116.          * only do this if there is nothing on the line
  117.          */
  118.           
  119.         parser_state_tos->ind_level -= ind_size;
  120.         /*
  121.          * it is a group as part of a while, for, etc.
  122.          */
  123.  
  124.         /* For -bl formatting, indent by brace_indent
  125.            additional spaces
  126.            e.g.
  127.            if (foo == bar)
  128.                {
  129.            <--> brace_indent spaces (in this example, 4)
  130.         */
  131.         if (!btype_2)
  132.           {
  133.             parser_state_tos->ind_level += brace_indent;
  134.             parser_state_tos->i_l_follow += brace_indent;
  135.             if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt)
  136.               case_ind += brace_indent;
  137.           }
  138.  
  139.         if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt
  140.             && case_indent
  141.             >= ind_size)
  142.           parser_state_tos->ind_level -= ind_size;
  143.         /*
  144.          * for a switch, brace should be two levels out from the code
  145.          */
  146.         }
  147.     }
  148.  
  149.     inc_pstack();
  150.     parser_state_tos->p_stack[parser_state_tos->tos] = lbrace;
  151.     parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
  152.     inc_pstack();
  153.     parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
  154.     /* allow null stmt between braces */
  155.     parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
  156.     break;
  157.  
  158.     case whilestmt:        /* scanned while (...) */
  159.     if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead) {
  160.         /* it is matched with do stmt */
  161.         parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
  162.         inc_pstack();
  163.         parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
  164.         parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  165.     }
  166.     else {            /* it is a while loop */
  167.       inc_pstack();
  168.       parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
  169.       parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
  170.       parser_state_tos->i_l_follow += ind_size;
  171.       parser_state_tos->search_brace = btype_2;
  172.     }
  173.  
  174.     break;
  175.  
  176.     case elselit:        /* scanned an else */
  177.  
  178.     if (parser_state_tos->p_stack[parser_state_tos->tos] != ifhead)
  179.         diag(1, "Unmatched 'else'");
  180.     else {
  181.         parser_state_tos->ind_level = parser_state_tos->il[parser_state_tos->tos];    /* indentation for else should
  182.                          * be same as for if */
  183.         /* everything following should be in 1 level */
  184.         parser_state_tos->i_l_follow = parser_state_tos->ind_level + ind_size;
  185.         
  186.         parser_state_tos->p_stack[parser_state_tos->tos] = elsehead;
  187.         /* remember if with else */
  188.         parser_state_tos->search_brace = btype_2 | else_if;
  189.     }
  190.     break;
  191.  
  192.     case rbrace:        /* scanned a } */
  193.     /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
  194.     if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == lbrace) {
  195.         parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[--parser_state_tos->tos];
  196.         parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
  197.     }
  198.     else
  199.         diag(1, "Stmt nesting error.");
  200.     break;
  201.  
  202.     case swstmt:        /* had switch (...) */
  203.     inc_pstack();
  204.     parser_state_tos->p_stack[parser_state_tos->tos] = swstmt;
  205.     parser_state_tos->cstk[parser_state_tos->tos] = case_ind;
  206.     /* save current case indent level */
  207.     parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
  208.     case_ind = parser_state_tos->i_l_follow + case_indent;    /* cases should be one
  209.                              * level down from
  210.                              * switch */
  211.     /* statements should be two levels in */
  212.     parser_state_tos->i_l_follow += case_indent + ind_size;
  213.  
  214.     parser_state_tos->search_brace = btype_2;
  215.     break;
  216.  
  217.     case semicolon:        /* this indicates a simple stmt */
  218.     break_comma = false;    /* turn off flag to break after commas in a
  219.                  * declaration */
  220.     inc_pstack();
  221.     parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
  222.     parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
  223.     break;
  224.  
  225.     default:            /* this is an error */
  226.     diag(1, "Unknown code to parser");
  227.     return;
  228.  
  229.  
  230.     }                /* end of switch */
  231.  
  232.     reduce();            /* see if any reduction can be done */
  233.  
  234. #ifdef debug
  235.     for (i = 1; i <= parser_state_tos->tos; ++i)
  236.     printf("(%d %d)", parser_state_tos->p_stack[i], parser_state_tos->il[i]);
  237.     printf("\n");
  238. #endif
  239.  
  240.     return;
  241. }
  242.  
  243. /*
  244.  * NAME: reduce
  245.  * 
  246.  * FUNCTION: Implements the reduce part of the parsing algorithm
  247.  * 
  248.  * ALGORITHM: The following reductions are done.  Reductions are repeated
  249.  *    until no more are possible.
  250.  * 
  251.  * Old TOS        New TOS
  252.  * <stmt> <stmt>    <stmtl>
  253.  * <stmtl> <stmt>    <stmtl>
  254.  * do <stmt>        "dostmt"
  255.  * if <stmt>        "ifstmt"
  256.  * switch <stmt>    <stmt>
  257.  * decl <stmt>        <stmt>
  258.  * "ifelse" <stmt>    <stmt>
  259.  * for <stmt>        <stmt>
  260.  * while <stmt>        <stmt>
  261.  * "dostmt" while    <stmt>
  262.  * 
  263.  * On each reduction, parser_state_tos->i_l_follow
  264.  * (the indentation for the following line) 
  265.  * is set to the indentation level associated with the old TOS.
  266.  * 
  267.  * PARAMETERS: None
  268.  * 
  269.  * RETURNS: Nothing
  270.  * 
  271.  * GLOBALS: parser_state_tos->cstk parser_state_tos->i_l_follow = parser_state_tos->il parser_state_tos->p_stack = parser_state_tos->tos =
  272.  * 
  273.  * CALLS: None
  274.  * 
  275.  * CALLED BY: parse 
  276.  * 
  277.  * HISTORY: initial coding     November 1976    D A Willcox of CAC
  278.  * 
  279.  */
  280. /*----------------------------------------------*\
  281. |   REDUCTION PHASE                    |
  282. \*----------------------------------------------*/
  283. reduce()
  284. {
  285.  
  286.     register int i;
  287.  
  288.     for (;;) {            /* keep looping until there is nothing left to
  289.                  * reduce */
  290.  
  291.     switch (parser_state_tos->p_stack[parser_state_tos->tos]) {
  292.  
  293.     case stmt:
  294.         switch (parser_state_tos->p_stack[parser_state_tos->tos - 1]) {
  295.  
  296.         case stmt:
  297.         case stmtl:
  298.         /* stmtl stmt or stmt stmt */
  299.         parser_state_tos->p_stack[--parser_state_tos->tos] = stmtl;
  300.         break;
  301.  
  302.         case dolit:    /* <do> <stmt> */
  303.         parser_state_tos->p_stack[--parser_state_tos->tos] = dohead;
  304.         parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
  305.         break;
  306.  
  307.         case ifstmt:
  308.         /* <if> <stmt> */
  309.         parser_state_tos->p_stack[--parser_state_tos->tos] = ifhead;
  310.         for (i = parser_state_tos->tos - 1;
  311.             (
  312.              parser_state_tos->p_stack[i] != stmt
  313.              &&
  314.              parser_state_tos->p_stack[i] != stmtl
  315.              &&
  316.              parser_state_tos->p_stack[i] != lbrace
  317.              );
  318.             --i);
  319.         parser_state_tos->i_l_follow = parser_state_tos->il[i];
  320.         /*
  321.          * for the time being, we will assume that there is no else on
  322.          * this if, and set the indentation level accordingly. If an
  323.          * else is scanned, it will be fixed up later
  324.          */
  325.         break;
  326.  
  327.         case swstmt:
  328.         /* <switch> <stmt> */
  329.         case_ind = parser_state_tos->cstk[parser_state_tos->tos - 1];
  330.  
  331.         case decl:        /* finish of a declaration */
  332.         case elsehead:
  333.         /* <<if> <stmt> else> <stmt> */
  334.         case forstmt:
  335.         /* <for> <stmt> */
  336.         case whilestmt:
  337.         /* <while> <stmt> */
  338.         parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
  339.         parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
  340.         break;
  341.  
  342.         default:        /* <anything else> <stmt> */
  343.         return;
  344.  
  345.         }            /* end of section for <stmt> on top of stack */
  346.         break;
  347.  
  348.     case whilestmt:    /* while (...) on top */
  349.         if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == dohead) {
  350.         /* it is termination of a do while */
  351.         parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
  352.         break;
  353.         }
  354.         else
  355.         return;
  356.  
  357.     default:        /* anything else on top */
  358.         return;
  359.  
  360.     }
  361.     }
  362. }
  363.